
#include <stdint.h>
#include "BitBuf.h"


void BitBuf_Init(BitBuf_T* bitbuf, uint32_t *bundle, uint32_t total_bits){
	bitbuf->bundles = bundle;
	bitbuf->num_bundles = (total_bits + bundle_bitness(bitbuf) - 1) / bundle_bitness(bitbuf);
	bitbuf->num_bits = total_bits;
}


int BitBuf_SetBit(BitBuf_T *bitbuf, uint32_t bit){
	uint32_t idx, off;

	if (bit >= bitbuf->num_bits) {
		return -1;
	}

	idx = bit / bundle_bitness(bitbuf);
	off = bit % bundle_bitness(bitbuf);

	bitbuf->bundles[idx] |= Bit(off);

	return 0;
}

int BitBuf_ClearBit(BitBuf_T *bitbuf, uint32_t bit){
	uint32_t idx, off;

	if (bit >= bitbuf->num_bits) {
		return -1;
	}

	idx = bit / bundle_bitness(bitbuf);
	off = bit % bundle_bitness(bitbuf);

	bitbuf->bundles[idx] &= ~ Bit(off);

	return 0;
}

int BitBuf_TestBit(BitBuf_T *bitbuf, uint32_t bit, int *val){
	uint32_t idx, off;

	if (bit >= bitbuf->num_bits) {
		return -1;
	}

	idx = bit / bundle_bitness(bitbuf);
	off = bit % bundle_bitness(bitbuf);

	*val = (bitbuf->bundles[idx] & Bit(off)) ? 1 : 0;

	return 0;
}

int BitBuf_GetBundle(BitBuf_T* bitbuf, uint32_t bit, BitBundle_T* bitbundle){
	uint32_t idx, off;
	int len;
	int num;
	int num_bundle;
	
	if (bit >= bitbuf->num_bits) {
		return -1;
	}
	
	if(bitbundle->num <= bitbundle->off){
		return 0;
	}
	
	len = bitbuf->num_bits - bit;
	num_bundle = (int)bitbundle->num - (int)bitbundle->off;
	if(num_bundle > len){
		num_bundle = len;
	}
	
	idx = bit / bundle_bitness(bitbuf);
	off = bit % bundle_bitness(bitbuf);
	//字内空间
	num = bundle_bitness(bitbuf) - off;
	if(num > num_bundle){
		num = num_bundle;
	}
	
	bitbundle->bundle = (bitbuf->bundles[idx] >> off) << bitbundle->off;
	bitbundle->off += num;
	
	return num;
}


int BitBuf_SetBundle(BitBuf_T* bitbuf, uint32_t bit, BitBundle_T* bitbundle){
	uint32_t idx, off;
	uint32_t eoff;
	uint32_t smask, emask;
	uint32_t mask;
	uint32_t bundle;
	int len;
	int num;
	int num_bundle;
	
	if (bit >= bitbuf->num_bits) {
		return -1;
	}
	
	if(bitbundle->num <= bitbundle->off){
		return 0;
	}
	
	num_bundle = (int)bitbundle->num - (int)bitbundle->off;
	len = bitbuf->num_bits - bit;
	if (num_bundle > len) {
		num_bundle = len;
	}

	idx = bit / bundle_bitness(bitbuf);
	off = bit % bundle_bitness(bitbuf);
	//字内空间
	num = bundle_bitness(bitbuf) - off;
	if(num > num_bundle){
		num = num_bundle;
	}
	
	bundle = bitbundle->bundle >> bitbundle->off;
	smask = ~(Bit(off) - 1);
	eoff = off + num;
	emask = (Bit(eoff) - 1);
	mask = smask & emask;
	bitbuf->bundles[idx] &= ~ mask;
	bitbuf->bundles[idx] |= (bundle << off) & mask;
	
	bitbundle->off += num;
	
	return num;
}



